home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / glibc-1.09 / glibc-1 / glibc-1.09.1 / resolv / getnetnamadr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-05  |  7.6 KB  |  296 lines

  1. /* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
  2.  *    Dep. Matematica Universidade de Coimbra, Portugal, Europe
  3.  */
  4. /*
  5.  * Copyright (c) 1983 Regents of the University of California.
  6.  * All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #if defined(LIBC_SCCS) && !defined(lint)
  38. static char sccsid[] = "@(#)getnetnamadr.c    1.4 (Coimbra) 93/06/03";
  39. static char rcsid[] = "$Id: getnetnamadr.c,v 1.2 1994/09/05 17:24:23 roland Exp $";
  40. #endif /* LIBC_SCCS and not lint */
  41.  
  42. #include <sys/param.h>
  43. #include <sys/socket.h>
  44. #include <netinet/in.h>
  45. #include <arpa/inet.h>
  46. #include <arpa/nameser.h>
  47.  
  48. #include <stdio.h>
  49. #include <netdb.h>
  50. #include <resolv.h>
  51. #include <ctype.h>
  52. #include <errno.h>
  53. #include <string.h>
  54.  
  55. extern int h_errno;
  56.  
  57. #if defined(mips) && defined(SYSTYPE_BSD43)
  58. extern int errno;
  59. #endif
  60.  
  61. struct netent *_getnetbyaddr __P((long net, int type));
  62. struct netent *_getnetbyname __P((const char *name));
  63.  
  64. #define BYADDR 0
  65. #define BYNAME 1
  66. #define    MAXALIASES    35
  67.  
  68. #if PACKETSZ > 1024
  69. #define    MAXPACKET    PACKETSZ
  70. #else
  71. #define    MAXPACKET    1024
  72. #endif
  73.  
  74. typedef union {
  75.     HEADER    hdr;
  76.     u_char    buf[MAXPACKET];
  77. } querybuf;
  78.  
  79. typedef union {
  80.     long    al;
  81.     char    ac;
  82. } align;
  83.  
  84. static struct netent *
  85. getnetanswer(answer, anslen, net_i)
  86.     querybuf *answer;
  87.     int anslen;
  88.     int net_i;
  89. {
  90.  
  91.     register HEADER    *hp;
  92.     register u_char    *cp;
  93.     register int    n;
  94.     u_char        *eom;
  95.     int        type, class, buflen, ancount, qdcount,
  96.             haveanswer, i, nchar,
  97.             getclass = C_ANY,
  98.             net_length = 0;
  99.     char        aux1[30], aux2[30], ans[30],
  100.             *in, *st, *pauxt, *bp, **ap,
  101.             *paux1 = &aux1[0],
  102.             *paux2 = &aux2[0],
  103.             flag = 0;
  104. static    struct netent    net_entry;
  105. static    char        *net_aliases[MAXALIASES],
  106.             netbuf[BUFSIZ+1];
  107.  
  108.     /*
  109.      * find first satisfactory answer
  110.      *
  111.      *      answer --> +------------+  ( MESSAGE )
  112.      *           |   Header   |
  113.      *           +------------+
  114.      *           |  Question  | the question for the name server
  115.      *           +------------+
  116.      *           |   Answer   | RRs answering the question
  117.      *           +------------+
  118.      *           | Authority  | RRs pointing toward an authority
  119.      *           | Additional | RRs holding additional information
  120.      *           +------------+
  121.      */
  122.     eom = answer->buf + anslen;
  123.     hp = &answer->hdr;
  124.     ancount = ntohs(hp->ancount); /* #/records in the answer section */
  125.     qdcount = ntohs(hp->qdcount); /* #/entries in the question section */
  126.     bp = netbuf;
  127.     buflen = sizeof(netbuf);
  128.     cp = answer->buf + HFIXEDSZ;
  129.     if (!qdcount) {
  130.         if (hp->aa)
  131.             h_errno = HOST_NOT_FOUND;
  132.         else
  133.             h_errno = TRY_AGAIN;
  134.  
  135.         return ((struct netent *) NULL);
  136.     }
  137.     while (qdcount-- > 0){
  138.         cp += __dn_skipname(cp, eom) + QFIXEDSZ;
  139.         }
  140.     ap = net_aliases;
  141.     *ap = NULL;
  142.     net_entry.n_aliases = net_aliases;
  143.     haveanswer = 0;
  144.     while (--ancount >= 0 && cp < eom) {
  145.         n = dn_expand(answer->buf, eom, cp, bp, buflen);
  146.         if (n < 0)
  147.             break;
  148.         cp += n;
  149.         ans[0] = '\0';
  150.         (void)strcpy(&ans[0], bp);
  151.         GETSHORT(type, cp);
  152.         GETSHORT(class, cp);
  153.         cp += INT32SZ;        /* TTL */
  154.         GETSHORT(n, cp);
  155.         if (class == C_IN && type == T_PTR) {
  156.             n = dn_expand(answer->buf, eom, cp, bp, buflen);
  157.             if (n < 0) {
  158.                 cp += n;
  159.                 return (NULL);
  160.             }
  161.             cp += n; 
  162.             *ap++ = bp;
  163.             bp += (strlen(bp) + 1);
  164.             net_entry.n_addrtype = (class == C_IN)
  165.                         ? AF_INET
  166.                         : AF_UNSPEC;
  167.             haveanswer++;
  168.         }
  169.     }
  170.     if (haveanswer) {
  171.         *ap = NULL;
  172.         switch (net_i) {
  173.            case BYADDR :
  174.             net_entry.n_name = *net_entry.n_aliases;
  175.             net_entry.n_net = 0L;
  176.             break;
  177.            case BYNAME :
  178.             in = *net_entry.n_aliases;
  179.             net_entry.n_name = &ans[0];
  180.             aux2[0] = '\0';
  181.             for (i = 0;  i < 4;  i++) {
  182.                 for (st = in, nchar = 0;
  183.                      *st != '.';
  184.                      st++, nchar++)
  185.                     ;
  186.                 if (nchar != 1 || *in != '0' || flag) {
  187.                     flag = 1;
  188.                     (void)strncpy(paux1,
  189.                               (i==0) ?in :in-1,
  190.                               (i==0) ?nchar :nchar+1);
  191.                     paux1[(i==0) ?nchar :nchar+1] = '\0';
  192.                     pauxt = paux2;
  193.                     paux2 = strcat(paux1, paux2);
  194.                     paux1 = pauxt;
  195.                 }
  196.                 in = ++st;
  197.             }          
  198.             net_entry.n_net = inet_network(paux2);
  199.         }
  200.         net_entry.n_aliases++;
  201.         return (&net_entry);
  202.     } else {
  203.         h_errno = TRY_AGAIN;
  204.         return ((struct netent *) NULL);
  205.     }
  206. }
  207.  
  208. struct netent *
  209. getnetbyaddr(net, net_type)
  210.     register long net;
  211.     register int net_type;
  212. {
  213.     unsigned int    netbr[4];
  214.     int        nn, anslen;
  215.     querybuf    buf;
  216.     char        qbuf[MAXDNAME];
  217.     unsigned long    net2;
  218.     struct netent    *net_entry;
  219.  
  220.     if (net_type != AF_INET)
  221.         return (_getnetbyaddr(net, net_type));
  222.  
  223.     for (nn = 4, net2 = net;  net2;  net2 >>= 8) {
  224.         netbr[--nn] = net2 & 0xff;
  225.     }
  226.     switch (nn) {
  227.         case 3:     /* Class A */
  228.             (void)sprintf(qbuf, "0.0.0.%u.in-addr.arpa",
  229.                       netbr[3]);
  230.             break;
  231.         case 2:     /* Class B */
  232.             (void)sprintf(qbuf, "0.0.%u.%u.in-addr.arpa",
  233.                       netbr[3], netbr[2]);
  234.             break;
  235.         case 1:     /* Class C */
  236.             (void)sprintf(qbuf, "0.%u.%u.%u.in-addr.arpa",
  237.                       netbr[3], netbr[2], netbr[1]);
  238.             break;
  239.         case 0:     /* Class D - E */
  240.             (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
  241.                       netbr[3], netbr[2], netbr[1], netbr[0]);
  242.             break;
  243.     }
  244.     anslen = res_query(qbuf, C_IN, T_PTR, buf.buf, sizeof buf.buf);
  245.     if (anslen < 0) {
  246. #ifdef DEBUG
  247.         if (_res.options & RES_DEBUG)
  248.             printf("res_query failed\n");
  249. #endif
  250.         if (errno == ECONNREFUSED)
  251.             return (_getnetbyaddr(net, net_type));
  252.         return (_getnetbyaddr(net, net_type));
  253.     }
  254.     net_entry = getnetanswer(&buf, anslen, BYADDR);
  255.     if (net_entry) {
  256.         unsigned u_net = net;    /* maybe net should be unsigned ? */
  257.  
  258.         /* Strip trailing zeros */
  259.         while ((u_net & 0xff) == 0 && u_net != 0) {
  260.             u_net >>= 8;
  261.         }
  262.         net_entry->n_net = u_net;
  263.         return (net_entry);
  264.     } else {
  265.         return (_getnetbyaddr(net, net_type));
  266.     }
  267. }
  268.  
  269. struct netent *
  270. getnetbyname(net)
  271.     register const char *net;
  272. {
  273.     unsigned int    netbr[4];
  274.     int        anslen;
  275.     querybuf    buf;
  276.     char        qbuf[MAXDNAME];
  277.     struct netent    *net_entry;
  278.        
  279.     (void)strcpy(&qbuf[0],net);
  280.     anslen = res_search(qbuf, C_IN, T_PTR, buf.buf, sizeof buf.buf);
  281.     if (anslen < 0) {
  282. #ifdef DEBUG
  283.         if (_res.options & RES_DEBUG)
  284.             printf("res_query failed\n");
  285. #endif
  286.         if (errno == ECONNREFUSED)
  287.             return (_getnetbyname(net));
  288.         return (_getnetbyname(net));
  289.     }
  290.     net_entry = getnetanswer(&buf, anslen, BYNAME);
  291.     if (net_entry)
  292.         return (net_entry);
  293.     else
  294.         return (_getnetbyname(net));
  295. }
  296.